home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
devices.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-03
|
9KB
|
403 lines
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
#include <netdb.h>
#include <net/if.h>
#include "netconf.h"
#include "internal.h"
#include "../misc/misc.h"
#include "../xconf/xconf.h"
#include "netconf.m"
/* #Specification: devices / management
netconf knows how to load a devices module (probing) and how
to configure it (ifconfig). It also knows how to update the
different routes.
*/
#
/*
Programme a network interface (ifconfig) only if needed,
Compare the current configuration with the expected configuration.
If there is a mismatch (or the interface is not configure), then
it is reconfigure with the expected values.
Return -1 if any error.
*/
static int devices_ifconfig(
const char *device,
const char *expected_hst,
const char *expected_msk)
{
IFCONFIG_INFO info;
int ret = ifconfig_getinfo (device,info);
if (ret == -1){
xconf_error (MSG_U(E_CANTPROBE
,"Can't probe current setup of network device %s\n"
"No way to activate the network\n")
,device);
}else{
DAEMON *dae = daemon_find ("ifconfig");
if (dae != NULL){
if (strcmp(info.ip_addr,expected_hst)==0
&& strcmp(info.netmask,expected_msk)==0
&& info.flags & IFF_UP){
ret = 0;
}else{
char cmd[300];
/* #Specification: netconf / ifconfig / down
We always force an interface DOWN
before reconfiguring it. It has
the side effect of cleaning the route
table for that device.
*/
sprintf (cmd,"%s down",device);
netconf_system_if ("ifconfig",cmd);
sprintf (cmd,"%s %s netmask %s",device,expected_hst
,expected_msk);
ret = netconf_system_if ("ifconfig",cmd);
}
}
}
return ret;
}
/*
Configure the loopback device.
Return -1 if any error.
*/
int netconf_setloopback()
{
/* #Specification: loopback / strategy
As far as I know, there is only a way to configure the
loopback device.
/sbin/ifconfig lo 127.0.0.1
/sbin/route add -net loopback
*/
int ret = devices_ifconfig ("lo","127.0.0.1","255.0.0.0");
if (ret == 0){
char gateway[PATH_MAX];
if (!route_isactive("127.0.0.0",gateway)){
ret = netconf_system_if ("route","add -net 127.0.0.0 lo");
}
}
return ret == 0 ? 0 : -1;
}
/*
Format in text the major IP number of a HOST
*/
void devices_ip2a(struct hostent *ent, char *buf)
{
unsigned char *numadr = (unsigned char *)ent->h_addr_list[0];
char *pt = buf;
int len = ent->h_length;
for (int i=0; i<len; i++){
pt += sprintf (pt,i==0 ? "%d":".%d",numadr[i]);
}
}
void devices_ip2a(struct hostent *ent, SSTRING &ip)
{
char buf[16];
devices_ip2a (ent,buf);
ip.setfrom (buf);
}
/*
Format in text an IP number
*/
void devices_ip2a(unsigned long ip, char *buf)
{
union{
long num;
unsigned char car[4];
}u;
u.num = ip;
sprintf (buf,"%d.%d.%d.%d",u.car[3],u.car[2],u.car[1],u.car[0]);
}
/*
Format in text the major IP number of a NET
*/
void devices_ip2a(struct netent *ent, char *buf)
{
devices_ip2a (ent->n_net,buf);
}
void devices_ip2a(struct netent *ent, SSTRING &ip)
{
char buf[16];
devices_ip2a (ent->n_net,buf);
ip.setfrom (buf);
}
/*
Translate an IP number (ascii) into four number
Return -1 if the IP number is invalid.
*/
int device_aip24 (const char *aip, int num4[4])
{
int ret = 0;
for (int i=0; i<4; i++){
if (!isdigit(aip[0])){
ret = -1;
break;
}else{
int no = num4[i] = atoi(aip);
if (no < 0 || no > 255) ret = -1;
while (isdigit(*aip)) aip++;
if (i < 3 && *aip != '.'){
ret = -1;
break;
}
aip++;
}
}
return ret;
}
/*
Check is a string is valid IP number.
if (ishost), check if the IP is not a broadcast or a network address.
*/
bool device_validip(const char *aip, bool ishost)
{
int num4[4];
bool ret = false;
if (device_aip24(aip,num4) != -1){
ret = true;
if (ishost && (num4[3] == 0 || num4[3] == 255)){
ret = false;
}
}
return ret;
}
#if 0
/*
Perform a gethostbyname with error reporting.
Return -1 if not found.
*/
static int devices_gethostbyname(
const char *host,
const char *device,
char *ip_num, // Will contain the formatted IP address
int silent) // Ok if not set, no error message
{
struct hostent *ent = gethostbyname(host);
int ret = -1;
if (ent == NULL){
if (!silent){
xconf_error ("%s is not defined\n"
"Can't configured device %s\n",host,device);
}
}else{
ret = 0;
devices_ip2a (ent,ip_num);
}
return ret;
}
/*
Perform a getnetbyname with error reporting.
Return -1 if not found.
*/
static int devices_getnetbyname(
const char *net,
const char *device,
char *ip_num, // Will contain the formatted IP address
int silent) // Ok if not set, no error message
{
struct netent *ent = getnetbyname(net);
int ret = -1;
if (ent == NULL){
if (!silent){
xconf_error ("%s is not defined\n"
"Can't configured device %s\n",net,device);
}
}else{
ret = 0;
devices_ip2a (ent,ip_num);
}
return ret;
}
#endif
struct IFACE_NUMS{
char hst[20];
char net[20];
char msk[20];
};
void device_setstdnetmask(
const char *hostip, // IP number of a HOST
char *def_net, // Default network number
char *def_msk) // Default netmask
{
int num4[4];
device_aip24 (hostip,num4);
if (num4[0] == 0){
strcpy (def_net,"0.0.0.0");
strcpy (def_msk,"0.0.0.0");
}else if (num4[0] <= 127){
sprintf (def_net,"%d.0.0.0",num4[0]);
strcpy (def_msk,"255.0.0.0");
}else if (num4[0] <= 191){
sprintf (def_net,"%d.%d.0.0"
,num4[0],num4[1]);
strcpy (def_msk,"255.255.0.0");
}else{
sprintf (def_net,"%d.%d.%d.0"
,num4[0],num4[1],num4[2]);
strcpy (def_msk,"255.255.255.0");
}
}
static int device_copystr (char *dst, SSTRING &src)
{
src.copy (dst);
return src.is_empty() ? -1 : 0;
}
/*
Get the IP number assigned to an interface (host,network and mask)
Fill default values if some information is not fully specified.
Return -1 if to much is missing.
*/
static int device_ifaceinfo (
const char *device, // Name of the device (for error report)
INTER_INFO &itf,
IFACE_NUMS &nums)
{
int ret = -1;
int h_ok = device_copystr (nums.hst,itf.ipaddr);
int n_ok = device_copystr (nums.net,itf.network);
int m_ok = device_copystr (nums.msk,itf.netmask);
if (h_ok != -1){
/* #Specification: ifconfig / eth devices / 127.0.0.1
Linuxconf won't configure an ethernet
interface to 127.0.0.1. It will simply ignore it.
This case happen when a properly configured
linux system without an ethernet adaptor get
one.
*/
if (strcmp(nums.hst,"127.0.0.1")!=0){
/* #Specification: ifconfig / netmask and network / optionnal
The netmask and network address of a network specification are
optionnal. The kernel (or ifconfig or route, I don't know)
compute suitable defaults.
*/
char def_net[20];
char def_msk[20];
device_setstdnetmask(nums.hst,def_net,def_msk);
if (n_ok == -1) strcpy (nums.net,def_net);
if (m_ok == -1) strcpy (nums.msk,def_msk);
ret = 0;
if (!device_validip(nums.hst,true)
|| !device_validip(nums.net,false)
|| !device_validip(nums.msk,false)){
ret = -1;
xconf_error (
"Invalid IP number for interface %s"
,device);
}
}
}
return ret;
}
/*
Load a network device module.
Return -1 if any error
*/
int device_insmod (const char *devname)
{
return netconf_system_if ("modprobe",devname);
}
/*
Initialise a network device and set the basic route to it.
*/
static int device_set (
int dev_exist, // Is the device configured in the kernel ?
const char *device, // Name of the device
INTER_INFO &itf)
{
int ret = -1;
IFACE_NUMS nums;
int ip_needed = device_ifaceinfo (device,itf,nums) != -1;
if (ip_needed){
/* #Specification: netconf / devices / modules
If a device (eth?) is not available in the kernel
linuxconf does a "modprobe device" to load the module.
*/
if (!dev_exist) dev_exist = device_insmod (device) != -1;
if (dev_exist){
if (ip_needed){
ret = devices_ifconfig(device,nums.hst,nums.msk);
if (ret == 0){
char cmd[300];
char gateway[PATH_MAX];
int status = route_isactive(nums.net,gateway);
if (status && strcmp(gateway,device)!=0){
sprintf (cmd,"del -net %s",nums.net);
ret = netconf_system_if ("route",cmd);
status = 0;
}
if (!status){
sprintf (cmd,"add -net %s %s",nums.net,device);
ret = netconf_system_if ("route",cmd);
}
}
}
}else{
xconf_error (MSG_U(E_NODEVICE
,"Networking was configured\n"
"for the interface %s\n"
"but this device is not configured\n"
"in the kernel\n")
,device);
}
}else if (!dev_exist){
// No configuration (IP or IPX) for this device
// but it is not there anyway
ret = 0;
}
return ret;
}
const char *tb_netdevices[]={
"eth0","eth1","eth2","eth3"
};
/*
Configure the main communication devices (ethernet) and set the
basic route.
Return -1 if any error.
*/
int netconf_setdevices()
{
/* #Specification: network devices / lookup
netconf finds out which permanent network devices do exist
by reading /proc/net/dev. Slip devices are ignored because
they are not managed properply by netconf right now.
In fact, netconf deal only with ETHx devices.
*/
int ret = 0;
HOSTINFO info;
if (netconf_loadinfos(info) != -1){
for (int i=0; i<NB_ETH; i++){
const char *devname = tb_netdevices[i];
ret |= device_set (devlist_devexist(devname)
,devname
,info.a[i]);
}
}
return ret;
}